/***************************************************************************\
 * Copyright (C) by Keio University
 * Pyramid.cpp created in 02 2012.
 * Mail : fdesorbi@hvrl.ics.keio.ac.jp
 *
 * Pyramid.cpp is part of the HVRL Engine Project.
 *
 * The HVRL Engine Project is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * The HVRL Engine Project is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 \***************************************************************************/

#include "hvrl/tools/Pyramid.hpp"

namespace hvrl {

Pyramid::Pyramid(void) {

	this->pyramid = 0;
	this->levels = 0;
	this->smoothingparameter = cv::Size(0, 0);
	this->subsamplingfactor = 1.0f;

}

Pyramid::Pyramid(const cv::Mat& inputimage, const unsigned int& levels,
		const float& ssfactor, const cv::Size& smoothing) {

	this->pyramid = 0;
	this->levels = 0;
	this->smoothingparameter = cv::Size(0, 0);
	this->subsamplingfactor = 1.0f;

	this->init(inputimage, levels, ssfactor, smoothing);

}

bool Pyramid::init(const cv::Mat& inputimage, const unsigned int& levels,
		const float& ssfactor, const cv::Size& smoothing) {

	this->levels = levels;
	this->smoothingparameter = smoothing;
	this->subsamplingfactor = ssfactor;

	// Check that all input parameters are correct
	if (this->levels == 0) {
		return false;
	}

	if (this->subsamplingfactor <= 0.0f || this->subsamplingfactor > 1.0f) {
		return false;
	}

	cv::Size inputimagesize = inputimage.size();
	if (float(
			inputimagesize.width / pow(1.0f / this->subsamplingfactor,
					int(this->levels - 1))) < 1.0f && float(
			inputimagesize.height / pow(1.0f / this->subsamplingfactor,
					int(this->levels - 1))) < 1.0f) {
		return false;
	}

	if (this->smoothingparameter.width <= 0 || this->smoothingparameter.height
			<= 0) {
		return false;
	}

	this->pyramid = new cv::Mat[this->levels];

	// Initialize the first level with the input image
	inputimage.copyTo(this->pyramid[0]);

	for(unsigned int i = 1; i < this->levels; ++i){
		cv::resize(this->pyramid[i-1],this->pyramid[i],cv::Size(0,0),this->subsamplingfactor,this->subsamplingfactor);
	}

	return true;

}


bool Pyramid::update(const cv::Mat& inputimage){
	if(this->pyramid){
		inputimage.copyTo(this->pyramid[0]);

		for(unsigned int i = 1; i < this->levels; ++i){
			cv::resize(this->pyramid[i-1],this->pyramid[i],cv::Size(0,0),this->subsamplingfactor,this->subsamplingfactor);
		}
		return true;
	}
	return false;
}


const cv::Mat& Pyramid::getLevel(const unsigned int& level) {
	if(level >= this->levels)
		return  this->pyramid[this->levels-1];
	return this->pyramid[level];
}

const unsigned int& Pyramid::getLevels(void) {
	return this->levels;
}

const float& Pyramid::getSubSamplingFactor(void) {
	return this->subsamplingfactor;
}

}
